#!/usr/bin/env python
# -*- encoding: utf-8 -*-

'''
Created on 2015年1月6日

@author: cuckoocs
'''

import os
import uuid
import sys
import re
import syslog
import subprocess
import datetime
import json
import ntpath
import plistlib
import shutil
from UserDict import IterableUserDict
from UserList import UserList
regex = '[a-zA-Z0-9\\._/-]*'

def mlog(flag, msg):
    print 'flag is:{}, message is:{}'.format(flag,msg)

class PBXEncoder(json.JSONEncoder):
    
    def default(self, obj):
        if isinstance(obj, (PBXList, PBXDict)):
            return obj.data
        return json.JSONEncoder.default(self, obj)



class PBXDict(IterableUserDict):
    
    def __init__(self, d = None):
        if d:
            continue
            d = _[1]([ (PBXType.Convert(k), PBXType.Convert(v)) for (k, v) in d.items() ])
        
        IterableUserDict.__init__(self, d)

    
    def __setitem__(self, key, value):
        IterableUserDict.__setitem__(self, PBXType.Convert(key), PBXType.Convert(value))

    
    def remove(self, key):
        self.data.pop(PBXType.Convert(key), None)



class PBXList(UserList):
    
    def __init__(self, l = None):
        if isinstance(l, basestring):
            UserList.__init__(self)
            self.add(l)
            return None
        if l:
            continue
            l = [ PBXType.Convert(v) for v in l ]
        
        UserList.__init__(self, l)

    
    def add(self, value):
        value = PBXType.Convert(value)
        if value in self.data:
            return False
        self.data.append(value)
        return True

    
    def remove(self, value):
        value = PBXType.Convert(value)
        if value in self.data:
            self.data.remove(value)
            return True
        return False

    
    def __setitem__(self, key, value):
        UserList.__setitem__(self, PBXType.Convert(key), PBXType.Convert(value))



class PBXType(PBXDict):
    
    def __init__(self, d = None):
        PBXDict.__init__(self, d)
        if 'isa' not in self:
            self['isa'] = self.__class__.__name__
        
        self.id = None

    
    def Convert(o):
        if isinstance(o, list):
            return PBXList(o)
        if isinstance(o, dict):
            isa = o.get('isa')
            if not isa:
                return PBXDict(o)
            cls = globals().get(isa)
            if cls and issubclass(cls, PBXType):
                return cls(o)
            print 'warning: unknown PBX type: %s' % isa
            return PBXDict(o)
        return o

    Convert = staticmethod(Convert)
    
    def IsGuid(o):
        return re.match('^[A-F0-9]{24}$', str(o))

    IsGuid = staticmethod(IsGuid)
    
    def GenerateId(cls):
        return ''.join(str(uuid.uuid4()).upper().split('-')[1:])

    GenerateId = classmethod(GenerateId)
    
    def Create(cls, *args, **kwargs):
        return cls(*args, **args)

    Create = classmethod(Create)


class PBXFileReference(PBXType):
    
    def __init__(self, d = None):
        PBXType.__init__(self, d)
        self.build_phase = None

    types = {
        '.a': ('archive.ar', 'PBXFrameworksBuildPhase'),
        '.app': ('wrapper.application', None),
        '.db': ('file', 'PBXResourcesBuildPhase'),
        '.s': ('sourcecode.asm', 'PBXSourcesBuildPhase'),
        '.c': ('sourcecode.c.c', 'PBXSourcesBuildPhase'),
        '.cpp': ('sourcecode.cpp.cpp', 'PBXSourcesBuildPhase'),
        '.framework': ('wrapper.framework', 'PBXFrameworksBuildPhase'),
        '.h': ('sourcecode.c.h', None),
        '.hpp': ('sourcecode.c.h', None),
        '.icns': ('image.icns', 'PBXResourcesBuildPhase'),
        '.m': ('sourcecode.c.objc', 'PBXSourcesBuildPhase'),
        '.j': ('sourcecode.c.objc', 'PBXSourcesBuildPhase'),
        '.mm': ('sourcecode.cpp.objcpp', 'PBXSourcesBuildPhase'),
        '.nib': ('wrapper.nib', 'PBXResourcesBuildPhase'),
        '.plist': ('text.plist.xml', 'PBXResourcesBuildPhase'),
        '.json': ('text.json', 'PBXResourcesBuildPhase'),
        '.png': ('image.png', 'PBXResourcesBuildPhase'),
        '.jpg': ('image.jpg', 'PBXResourcesBuildPhase'),
        '.rtf': ('text.rtf', 'PBXResourcesBuildPhase'),
        '.sql': ('file', 'PBXResourcesBuildPhase'),
        '.tiff': ('image.tiff', 'PBXResourcesBuildPhase'),
        '.txt': ('text', 'PBXResourcesBuildPhase'),
        '.html': ('text.html', 'PBXResourcesBuildPhase'),
        '.xcdatamodel': ('wrapper.xcdatamodel', 'PBXResourcesBuildPhase'),
        '.zip': ('archive.zip', 'PBXResourcesBuildPhase'),
        '.xcodeproj': ('wrapper.pb-project', None),
        '.xib': ('file.xib', 'PBXResourcesBuildPhase'),
        '.strings': ('text.plist.strings', 'PBXResourcesBuildPhase'),
        '.bundle': ('wrapper.plug-in', 'PBXResourcesBuildPhase'),
        '.dylib': ('compiled.mach-o.dylib', 'PBXFrameworksBuildPhase') }
    trees = [
        '<absolute>',
        '<group>',
        'BUILT_PRODUCTS_DIR',
        'DEVELOPER_DIR',
        'SDKROOT',
        'SOURCE_ROOT']
    
    def guess_file_type(self, ignore_unknown_type = False):
        self.remove('explicitFileType')
        self.remove('lastKnownFileType')
        ext = os.path.splitext(self.get('name', ''))[1]
        if os.path.isdir(self.get('path')) and ext != '.framework' and ext != '.bundle':
            f_type = 'folder'
            build_phase = None
            ext = ''
        else:
            (f_type, build_phase) = PBXFileReference.types.get(ext, ('?', 'PBXResourcesBuildPhase'))
        self['lastKnownFileType'] = f_type
        self.build_phase = build_phase
        if f_type == '?' and not ignore_unknown_type:
            print 'unknown file extension: %s' % ext
            print 'please add extension and Xcode type to PBXFileReference.types'
        
        return f_type

    
    def set_file_type(self, ft):
        self.remove('explicitFileType')
        self.remove('lastKnownFileType')
        self['explicitFileType'] = ft

    
    def Create(cls, os_path, tree = 'SOURCE_ROOT', ignore_unknown_type = False):
        if tree not in cls.trees:
            print 'Not a valid sourceTree type: %s' % tree
            return None
        fr = cls()
        fr.id = cls.GenerateId()
        fr['path'] = os_path
        fr['name'] = os.path.split(os_path)[1]
        if os.path.isabs(os_path):
            pass
        1
        fr['sourceTree'] = tree
        fr.guess_file_type(ignore_unknown_type = ignore_unknown_type)
        return fr

    Create = classmethod(Create)


class PBXBuildFile(PBXType):
    
    def set_weak_link(self, weak = False):
        k_settings = 'settings'
        k_attributes = 'ATTRIBUTES'
        s = self.get(k_settings)
        if not s:
            if weak:
                self[k_settings] = PBXDict({
                    k_attributes: PBXList([
                        'Weak']) })
            
            return True
        atr = s.get(k_attributes)
        if not atr:
            if weak:
                atr = PBXList()
            else:
                return False
        if weak:
            atr.add('Weak')
        else:
            atr.remove('Weak')
        self[k_settings][k_attributes] = atr
        return True

    
    def add_compiler_flag(self, flag):
        k_settings = 'settings'
        k_attributes = 'COMPILER_FLAGS'
        if k_settings not in self:
            self[k_settings] = PBXDict()
        
        if k_attributes not in self[k_settings]:
            self[k_settings][k_attributes] = flag
            return True
        flags = self[k_settings][k_attributes].split(' ')
        if flag in flags:
            return False
        flags.append(flag)
        self[k_settings][k_attributes] = ' '.join(flags)

    
    def Create(cls, file_ref, weak = False):
        if isinstance(file_ref, PBXFileReference):
            file_ref = file_ref.id
        
        bf = cls()
        bf.id = cls.GenerateId()
        bf['fileRef'] = file_ref
        if weak:
            bf.set_weak_link(True)
        
        return bf

    Create = classmethod(Create)


class PBXGroup(PBXType):
    
    def add_child(self, ref):
        if not isinstance(ref, PBXDict):
            return None
        isa = ref.get('isa')
        if isa != 'PBXFileReference' and isa != 'PBXGroup':
            return None
        if 'children' not in self:
            self['children'] = PBXList()
        
        self['children'].insert(0, ref.id)
        return ref.id

    
    def remove_child(self, id):
        if 'children' not in self:
            self['children'] = PBXList()
            return None
        if not PBXType.IsGuid(id):
            id = id.id
        
        self['children'].remove(id)

    
    def has_child(self, id):
        if 'children' not in self:
            self['children'] = PBXList()
            return False
        if not PBXType.IsGuid(id):
            id = id.id
        
        return id in self['children']

    
    def get_name(self):
        path_name = os.path.split(self.get('path', ''))[1]
        return self.get('name', path_name)

    
    def Create(cls, name, path = None, tree = 'SOURCE_ROOT'):
        grp = cls()
        grp.id = cls.GenerateId()
        grp['name'] = name
        grp['children'] = PBXList()
        if path:
            grp['path'] = path
            grp['sourceTree'] = tree
        else:
            grp['sourceTree'] = '<group>'
        return grp

    Create = classmethod(Create)


class PBXNativeTarget(PBXType):
    pass


class PBXProject(PBXType):
    pass


class PBXContainerItemProxy(PBXType):
    pass


class PBXReferenceProxy(PBXType):
    pass


class PBXVariantGroup(PBXType):
    pass


class PBXTargetDependency(PBXType):
    pass


class PBXAggregateTarget(PBXType):
    pass


class PBXHeadersBuildPhase(PBXType):
    pass


class PBXBuildPhase(PBXType):
    
    def add_build_file(self, bf):
        if bf.get('isa') != 'PBXBuildFile':
            return False
        if 'files' not in self:
            self['files'] = PBXList()
        
        self['files'].add(bf.id)
        return True

    
    def remove_build_file(self, id):
        if 'files' not in self:
            self['files'] = PBXList()
            return None
        self['files'].remove(id)

    
    def has_build_file(self, id):
        if 'files' not in self:
            self['files'] = PBXList()
            return False
        if not PBXType.IsGuid(id):
            id = id.id
        
        return id in self['files']



class PBXFrameworksBuildPhase(PBXBuildPhase):
    pass


class PBXResourcesBuildPhase(PBXBuildPhase):
    pass


class PBXShellScriptBuildPhase(PBXBuildPhase):
    
    def Create(cls, script, shell = '/bin/sh', files = [], input_paths = [], output_paths = [], show_in_log = '0'):
        bf = cls()
        bf.id = cls.GenerateId()
        bf['files'] = files
        bf['inputPaths'] = input_paths
        bf['outputPaths'] = output_paths
        bf['runOnlyForDeploymentPostprocessing'] = '0'
        bf['shellPath'] = shell
        bf['shellScript'] = script
        bf['showEnvVarsInLog'] = show_in_log
        return bf

    Create = classmethod(Create)


class PBXSourcesBuildPhase(PBXBuildPhase):
    pass


class PBXCopyFilesBuildPhase(PBXBuildPhase):
    pass


class XCBuildConfiguration(PBXType):
    
    def add_search_paths(self, paths, base, key, recursive = True, escape = True):
        modified = False
        if not isinstance(paths, list):
            paths = [
                paths]
        
        if base not in self:
            self[base] = PBXDict()
        
        for path in paths:
            if recursive and not path.endswith('/**'):
                path = os.path.join(path, '**')
            
            if key not in self[base]:
                self[base][key] = PBXList()
            elif isinstance(self[base][key], basestring):
                self[base][key] = PBXList(self[base][key])
            
            if escape:
                if self[base][key].add('"%s"' % path):
                    modified = True
                
            self[base][key].add('"%s"' % path)
            if self[base][key].add(path):
                modified = True
                continue
        
        return modified

    
    def add_header_search_paths(self, paths, recursive = True):
        return self.add_search_paths(paths, 'buildSettings', 'HEADER_SEARCH_PATHS', recursive = recursive)

    
    def add_library_search_paths(self, paths, recursive = True):
        return self.add_search_paths(paths, 'buildSettings', 'LIBRARY_SEARCH_PATHS', recursive = recursive)

    
    def add_framework_search_paths(self, paths, recursive = True):
        return self.add_search_paths(paths, 'buildSettings', 'FRAMEWORK_SEARCH_PATHS', recursive = recursive)

    
    def add_preprocessor_macro(self, flags):
        modified = False
        base = 'buildSettings'
        key = 'GCC_PREPROCESSOR_DEFINITIONS'
        if isinstance(flags, basestring):
            flags = PBXList(flags)
        
        if base not in self:
            self[base] = PBXDict()
        
        for flag in flags:
            if key not in self[base]:
                self[base][key] = PBXList()
            elif isinstance(self[base][key], basestring):
                self[base][key] = PBXList(self[base][key])
            
            if self[base][key].add(flag):
                continue
                self[base][key] = _[1]
                modified = True
                continue
            []
        
        return modified

    
    def add_other_cflags(self, flags):
        modified = False
        base = 'buildSettings'
        key = 'OTHER_CFLAGS'
        if isinstance(flags, basestring):
            flags = PBXList(flags)
        
        if base not in self:
            self[base] = PBXDict()
        
        for flag in flags:
            if key not in self[base]:
                self[base][key] = PBXList()
            elif isinstance(self[base][key], basestring):
                self[base][key] = PBXList(self[base][key])
            
            if self[base][key].add(flag):
                continue
                self[base][key] = _[1]
                modified = True
                continue
            []
        
        return modified

    
    def add_other_ldflags(self, flags):
        modified = False
        base = 'buildSettings'
        key = 'OTHER_LDFLAGS'
        if isinstance(flags, basestring):
            flags = PBXList(flags)
        
        if base not in self:
            self[base] = PBXDict()
        
        for flag in flags:
            if key not in self[base]:
                self[base][key] = PBXList()
            elif isinstance(self[base][key], basestring):
                self[base][key] = PBXList(self[base][key])
            
            if self[base][key].add(flag):
                continue
                self[base][key] = _[1]
                modified = True
                continue
            []
        
        return modified

    
    def remove_other_ldflags(self, flags):
        modified = False
        base = 'buildSettings'
        key = 'OTHER_LDFLAGS'
        if isinstance(flags, basestring):
            flags = PBXList(flags)
        
        if base in self:
            for flag in flags:
                if key not in self[base]:
                    return False
                if isinstance(self[base][key], basestring):
                    self[base][key] = PBXList(self[base][key])
                
                if self[base][key].remove(flag):
                    continue
                    self[base][key] = _[1]
                    modified = True
                    continue
                []
            
        
        return modified

    
    def modify_build_setting(self, setting_key, setting_value):
        modified = False
        base = 'buildSettings'
        if base in self:
            if setting_key not in self[base]:
                self[base][setting_key] = setting_value
            
            self[base][setting_key] = setting_value
            modified = True
        
        return modified



class XCConfigurationList(PBXType):
    pass


class XcodeProject(PBXDict):
    plutil_path = 'plutil'
    special_folders = [
        '.bundle',
        '.framework',
        '.xcodeproj']
    
    def __init__(self, d = None, path = None):
        syslog.openlog('Prime31')
        if not path:
            path = os.path.join(os.getcwd(), 'project.pbxproj')
        
        self.pbxproj_path = os.path.abspath(path)
        self.source_root = os.path.abspath(os.path.join(os.path.split(path)[0], '..'))
        IterableUserDict.__init__(self, d)
        self.data = PBXDict(self.data)
        self.objects = self.get('objects')
        self.modified = False
        root_id = self.get('rootObject')
        if root_id:
            self.root_object = self.objects[root_id]
            root_group_id = self.root_object.get('mainGroup')
            self.root_group = self.objects[root_group_id]
        else:
            print 'error: project has no root object'
            self.root_object = None
            self.root_group = None
        for (k, v) in self.objects.iteritems():
            v.id = k
        

    
    def log(self, message):
        syslog.syslog(syslog.LOG_ALERT, message)

    
    def add_preprocessor_macro(self, flags):
        continue
        build_configs = _[1]
        for b in build_configs:
            if b.add_preprocessor_macro(flags):
                self.modified = True
                continue
            []
        

    
    def add_other_cflags(self, flags):
        continue
        build_configs = _[1]
        for b in build_configs:
            if b.add_other_cflags(flags):
                self.modified = True
                continue
            []
        

    
    def add_other_ldflags(self, flags):
        continue
        build_configs = _[1]
        for b in build_configs:
            if b.add_other_ldflags(flags):
                self.modified = True
                continue
            []
        

    
    def remove_other_ldflags(self, flags):
        continue
        build_configs = _[1]
        for b in build_configs:
            if b.remove_other_ldflags(flags):
                self.modified = True
                continue
            []
        

    
    def modify_build_setting(self, setting_key, setting_value):
        continue
        build_configs = _[1]
        for b in build_configs:
            if b.modify_build_setting(setting_key, setting_value):
                self.modified = True
                continue
            []
        

    
    def add_header_search_paths(self, paths, recursive = True):
        continue
        build_configs = _[1]
        for b in build_configs:
            if b.add_header_search_paths(paths, recursive):
                self.modified = True
                continue
            []
        

    
    def add_framework_search_paths(self, paths, recursive = True):
        continue
        build_configs = _[1]
        for b in build_configs:
            if b.add_framework_search_paths(paths, recursive):
                self.modified = True
                continue
            []
        

    
    def add_library_search_paths(self, paths, recursive = True):
        continue
        build_configs = _[1]
        for b in build_configs:
            if b.add_library_search_paths(paths, recursive):
                self.modified = True
                continue
            []
        

    
    def get_obj(self, id):
        return self.objects.get(id)

    
    def get_ids(self):
        return self.objects.keys()

    
    def get_files_by_os_path(self, os_path, tree = 'SOURCE_ROOT'):
        continue
        files = _[1]
        return files

    
    def get_files_by_name(self, name, parent = None):
        if parent:
            continue
            files = _[1]
        
        files = parent
        return files

    
    def get_build_files(self, id):
        continue
        files = _[1]
        return files

    
    def get_groups_by_name(self, name, parent = None):
        if parent:
            continue
            groups = _[1]
        
        groups = parent
        return groups

    
    def get_or_create_group(self, name, path = None, parent = None):
        if not name:
            return None
        if not parent:
            parent = self.root_group
        elif not isinstance(parent, PBXGroup):
            parent = self.objects.get(parent, self.root_group)
        
        groups = self.get_groups_by_name(name)
        for grp in groups:
            if parent.has_child(grp.id):
                return grp
        
        grp = PBXGroup.Create(name, path)
        parent.add_child(grp)
        self.objects[grp.id] = grp
        self.modified = True
        return grp

    
    def has_group(self, name, path = None, parent = None):
        if not name:
            return None
        if not parent:
            parent = self.root_group
        elif not isinstance(parent, PBXGroup):
            parent = self.objects.get(parent, self.root_group)
        
        groups = self.get_groups_by_name(name)
        for grp in groups:
            if parent.has_child(grp.id):
                return True
        
        return False

    
    def get_groups_by_os_path(self, path):
        path = os.path.abspath(path)
        continue
        groups = _[1]
        return groups

    
    def get_build_phases(self, phase_name):
        continue
        phases = _[1]
        return phases

    
    def get_relative_path(self, os_path):
        return os.path.relpath(os_path, self.source_root)

    
    def verify_files(self, file_list, parent = None):
        if not file_list:
            return []
        if parent:
            continue
            exists_list = _[1]
        
        exists_list = parent
        return set(file_list).difference(exists_list)

    
    def add_run_script(self, target, script = None):
        result = []
        continue
        targets = _[1]
        if len(targets) != 0:
            script_phase = PBXShellScriptBuildPhase.Create(script)
            for t in targets:
                skip = False
                for buildPhase in t['buildPhases']:
                    if self.objects[buildPhase].get('isa') == 'PBXShellScriptBuildPhase' and self.objects[buildPhase].get('shellScript') == script:
                        skip = True
                        continue
                    []
                
                if not skip:
                    t['buildPhases'].add(script_phase.id)
                    self.objects[script_phase.id] = script_phase
                    result.append(script_phase)
                    continue
            
        
        return result

    
    def add_run_script_all_targets(self, script = None):
        result = []
        targets = self.get_build_phases('PBXNativeTarget') + self.get_build_phases('PBXAggregateTarget')
        if len(targets) != 0:
            script_phase = PBXShellScriptBuildPhase.Create(script)
            for t in targets:
                skip = False
                for buildPhase in t['buildPhases']:
                    if self.objects[buildPhase].get('isa') == 'PBXShellScriptBuildPhase' and self.objects[buildPhase].get('shellScript') == script:
                        skip = True
                        continue
                
                if not skip:
                    t['buildPhases'].add(script_phase.id)
                    self.objects[script_phase.id] = script_phase
                    result.append(script_phase)
                    continue
            
        
        return result

    
    def add_folder(self, os_path, parent = None, excludes = None, recursive = True, create_build_files = True):
        if not os.path.isdir(os_path):
            return []
        if not excludes:
            excludes = []
        
        results = []
        if not parent:
            parent = self.root_group
        elif not isinstance(parent, PBXGroup):
            parent = self.objects.get(parent, self.root_group)
        
        path_dict = {
            os.path.split(os_path)[0]: parent }
        special_list = []
        for (grp_path, subdirs, files) in os.walk(os_path):
            (parent_folder, folder_name) = os.path.split(grp_path)
            parent = path_dict.get(parent_folder, parent)
            continue
            if _[1]:
                continue
            
            if folder_name.startswith('.'):
                special_list.append(grp_path)
                continue
            
            if os.path.splitext(grp_path)[1] in XcodeProject.special_folders:
                special_list.append(grp_path)
                new_files = self.verify_files([
                    folder_name], parent = parent)
                if new_files:
                    results.extend(self.add_file(grp_path, parent, create_build_files = create_build_files))
                    continue
                []
                continue
            
            grp = self.get_or_create_group(folder_name, path = self.get_relative_path(grp_path), parent = parent)
            path_dict[grp_path] = grp
            results.append(grp)
            file_dict = { }
            for f in files:
                if not f[0] == '.':
                    continue
                    if _[2]:
                        continue
                    
                kwds = {
                    'create_build_files': create_build_files,
                    'parent': grp,
                    'name': f }
                f_path = os.path.join(grp_path, f)
                file_dict[f_path] = kwds
            
            continue
            new_files = _[3]([ n.get('name') for n in file_dict.values() ], parent = grp)
            continue
            add_files = _[4]
            for (path, kwds) in add_files:
                kwds.pop('name', None)
                results.extend(self.add_file(path, **None))
            
            if not recursive:
                break
                continue
            []
        
        for r in results:
            self.objects[r.id] = r
        
        return results

    
    def path_leaf(self, path):
        (head, tail) = ntpath.split(path)
        if not tail:
            pass
        return ntpath.basename(head)

    
    def add_file_if_doesnt_exist(self, f_path, parent = None, tree = 'SOURCE_ROOT', create_build_files = True, weak = False, ignore_unknown_type = False):
        for obj in self.objects.values():
            if 'path' in obj:
                if self.path_leaf(f_path) == self.path_leaf(obj.get('path')):
                    return []
                continue
            self.path_leaf(f_path) == self.path_leaf(obj.get('path'))
        
        return self.add_file(f_path, parent, tree, create_build_files, weak, ignore_unknown_type = ignore_unknown_type)

    
    def add_file(self, f_path, parent = None, tree = 'SOURCE_ROOT', create_build_files = True, weak = False, ignore_unknown_type = False):
        results = []
        abs_path = ''
        if os.path.isabs(f_path):
            abs_path = f_path
            if not os.path.exists(f_path):
                return results
            if tree == 'SOURCE_ROOT':
                f_path = os.path.relpath(f_path, self.source_root)
            else:
                tree = '<absolute>'
        
        if not parent:
            parent = self.root_group
        elif not isinstance(parent, PBXGroup):
            parent = self.objects.get(parent, self.root_group)
        
        file_ref = PBXFileReference.Create(f_path, tree, ignore_unknown_type = ignore_unknown_type)
        parent.add_child(file_ref)
        results.append(file_ref)
        if file_ref.build_phase and create_build_files:
            phases = self.get_build_phases(file_ref.build_phase)
            for phase in phases:
                build_file = PBXBuildFile.Create(file_ref, weak = weak)
                phase.add_build_file(build_file)
                results.append(build_file)
            
            if abs_path and tree == 'SOURCE_ROOT' and os.path.isfile(abs_path) and file_ref.build_phase == 'PBXFrameworksBuildPhase':
                library_path = os.path.join('$(SRCROOT)', os.path.split(f_path)[0])
                self.add_library_search_paths([
                    library_path], recursive = False)
            
            if abs_path and tree == 'SOURCE_ROOT' and not os.path.isfile(abs_path) and file_ref.build_phase == 'PBXFrameworksBuildPhase':
                framework_path = os.path.join('$(SRCROOT)', os.path.split(f_path)[0])
                self.add_framework_search_paths([
                    framework_path,
                    '$(inherited)'], recursive = False)
            
        
        for r in results:
            self.objects[r.id] = r
        
        if results:
            self.modified = True
        
        return results

    
    def check_and_repair_framework(self, base):
        name = os.path.basename(base)
        if '.framework' in name:
            basename = name[:-len('.framework')]
            finalHeaders = os.path.join(base, 'Headers')
            finalCurrent = os.path.join(base, 'Versions/Current')
            finalLib = os.path.join(base, basename)
            srcHeaders = 'Versions/A/Headers'
            srcCurrent = 'A'
            srcLib = 'Versions/A/' + basename
            if not os.path.exists(finalHeaders):
                os.symlink(srcHeaders, finalHeaders)
            
            if not os.path.exists(finalCurrent):
                os.symlink(srcCurrent, finalCurrent)
            
            if not os.path.exists(finalLib):
                os.symlink(srcLib, finalLib)
            
        

    
    def remove_group(self, grp):
        pass

    
    def remove_file(self, id, recursive = True):
        if not PBXType.IsGuid(id):
            id = id.id
        
        if id in self.objects:
            self.objects.remove(id)
            if recursive:
                continue
                groups = _[1]
                for group in groups:
                    if id in group['children']:
                        group.remove_child(id)
                        continue
                    []
                
            
            self.modified = True
        

    
    def move_file(self, id, dest_grp = None):
        pass

    
    def apply_patch(self, patch_path, xcode_path):
        if not os.path.isfile(patch_path) or not os.path.isdir(xcode_path):
            print 'ERROR: couldn\'t apply "%s" to "%s"' % (patch_path, xcode_path)
            return None
        print 'applying "%s" to "%s"' % (patch_path, xcode_path)
        return subprocess.call([
            'patch',
            '-p1',
            '--forward',
            '--directory=%s' % xcode_path,
            '--input=%s' % patch_path])

    
    def apply_mods(self, mod_dict, default_path = None):
        if not default_path:
            default_path = os.getcwd()
        
        keys = mod_dict.keys()
        for k in keys:
            v = mod_dict.pop(k)
            mod_dict[k.lower()] = v
        
        parent = mod_dict.pop('group', None)
        if parent:
            parent = self.get_or_create_group(parent)
        
        excludes = mod_dict.pop('excludes', [])
        if excludes:
            continue
            excludes = [ re.compile(e) for e in excludes ]
        
        compiler_flags = mod_dict.pop('compiler_flags', { })
        for (k, v) in mod_dict.items():
            if k == 'patches':
                for p in v:
                    if not os.path.isabs(p):
                        p = os.path.join(default_path, p)
                    
                    self.apply_patch(p, self.source_root)
                
            if k == 'folders':
                for folder in v:
                    kwds = { }
                    if ':' in folder:
                        args = folder.split(':')
                        kwds['recursive'] = False
                        folder = args.pop(0)
                    
                    if os.path.isabs(folder) and os.path.isdir(folder):
                        pass
                    1
                    folder = os.path.join(default_path, folder)
                    if not os.path.isdir(folder):
                        continue
                    
                    if parent:
                        kwds['parent'] = parent
                    
                    if excludes:
                        kwds['excludes'] = excludes
                    
                    self.add_folder(folder, **None)
                
            if k == 'headerpaths' or k == 'librarypaths':
                paths = []
                for p in v:
                    if p.endswith('/**'):
                        p = os.path.split(p)[0]
                    
                    if not os.path.isabs(p):
                        p = os.path.join(default_path, p)
                    
                    if not os.path.exists(p):
                        continue
                    
                    p = self.get_relative_path(p)
                    paths.append(os.path.join('$(SRCROOT)', p, '**'))
                
                if k == 'headerpaths':
                    self.add_header_search_paths(paths)
                else:
                    self.add_library_search_paths(paths)
            k == 'headerpaths'
            if k == 'other_cflags':
                self.add_other_cflags(v)
                continue
            if k == 'other_ldflags':
                self.add_other_ldflags(v)
                continue
            if k == 'libs' and k == 'frameworks' or k == 'files':
                paths = { }
                for p in v:
                    kwds = { }
                    if ':' in p:
                        args = p.split(':')
                        p = args.pop(0)
                        if 'weak' in args:
                            kwds['weak'] = True
                        
                    
                    file_path = os.path.join(default_path, p)
                    (search_path, file_name) = os.path.split(file_path)
                    continue
                    if _[2]:
                        continue
                    
                    
                    try:
                        expr = re.compile(file_name)
                    except re.error:
                        []
                        expr = None
                    except:
                        []

                    if expr and os.path.isdir(search_path):
                        file_list = os.listdir(search_path)
                        for f in file_list:
                            continue
                            if _[3]:
                                continue
                            
                            if re.search(expr, f):
                                kwds['name'] = f
                                paths[os.path.join(search_path, f)] = kwds
                                p = None
                                continue
                            []
                        
                    
                    if k == 'libs':
                        kwds['parent'] = self.get_or_create_group('Libraries', parent = parent)
                    elif k == 'frameworks':
                        kwds['parent'] = self.get_or_create_group('Frameworks', parent = parent)
                    
                    if p:
                        kwds['name'] = file_name
                        if k == 'libs':
                            p = os.path.join('usr', 'lib', p)
                            kwds['tree'] = 'SDKROOT'
                        elif k == 'frameworks':
                            p = os.path.join('System', 'Library', 'Frameworks', p)
                            kwds['tree'] = 'SDKROOT'
                        elif k == 'files' and not os.path.exists(file_path):
                            continue
                        
                        paths[p] = kwds
                        continue
                
                continue
                new_files = _[4]([ n.get('name') for n in paths.values() ])
                continue
                add_files = _[5]
                for (path, kwds) in add_files:
                    kwds.pop('name', None)
                    if 'parent' not in kwds and parent:
                        kwds['parent'] = parent
                    
                    self.add_file(path, **None)
                
            []
        
        if compiler_flags:
            for (k, v) in compiler_flags.items():
                filerefs = []
                for f in v:
                    continue
                    [](_[6])
                
                continue
                buildfiles = _[7]
                for bf in buildfiles:
                    if bf.add_compiler_flag(k):
                        self.modified = True
                        continue
                    []
                
            
        

    
    def backup(self, file_name = None, backup_name = None):
        if not file_name:
            file_name = self.pbxproj_path
        
        if not backup_name:
            backup_name = '%s.%s.backup' % (file_name, datetime.datetime.now().strftime('%d%m%y-%H%M%S'))
        
        shutil.copy2(file_name, backup_name)

    
    def save(self, file_name = None, old_format = False):
        if old_format:
            self.saveFormatXML(file_name)
        else:
            self.saveFormat3_2(file_name)

    
    def saveFormat3_2(self, file_name = None):
        self.save_new_format(file_name)

    
    def save_format_xml(self, file_name = None):
        if not file_name:
            file_name = self.pbxproj_path
        
        
        try:
            f = _[1]
            writer = PBXWriter(f)
            writer.writeln('<plist version="1.0">')
            writer.writeValue(self.data)
            writer.writeln('</plist>')
        finally:
            pass


    
    def save_new_format(self, file_name = None):
        if not file_name:
            file_name = self.pbxproj_path
        
        objs = self.data.get('objects')
        sections = dict()
        uuids = dict()
        for key in objs:
            l = list()
            if objs.get(key).get('isa') in sections:
                l = sections.get(objs.get(key).get('isa'))
            
            l.append(tuple([
                key,
                objs.get(key)]))
            sections[objs.get(key).get('isa')] = l
            if 'name' in objs.get(key):
                uuids[key] = objs.get(key).get('name')
                continue
            if 'path' in objs.get(key):
                uuids[key] = objs.get(key).get('path')
                continue
            if objs.get(key).get('isa') == 'PBXProject':
                uuids[objs.get(key).get('buildConfigurationList')] = 'Build configuration list for PBXProject "Unity-iPhone"'
                continue
            if objs.get(key).get('isa')[0:3] == 'PBX':
                uuids[key] = objs.get(key).get('isa')[3:-10]
                continue
            uuids[key] = 'Build configuration list for PBXNativeTarget "TARGET_NAME"'
        
        ro = self.data.get('rootObject')
        uuids[ro] = 'Project Object'
        for key in objs:
            if 'fileRef' in objs.get(key) and objs.get(key).get('fileRef') in uuids:
                uuids[key] = uuids[objs.get(key).get('fileRef')]
            
            if objs.get(key).get('isa') == 'PBXNativeTarget':
                uuids[objs.get(key).get('buildConfigurationList')] = uuids[objs.get(key).get('buildConfigurationList')].replace('TARGET_NAME', uuids[key])
                continue
        
        self.uuids = uuids
        self.sections = sections
        out = open(file_name, 'w')
        out.write('// !$*UTF8*$!\n')
        self._printNewXCodeFormat(out, self.data, '', enters = True)
        out.close()

    
    def addslashes(cls, s):
        d = {
            '"': '\\"',
            "'": "\\'",
            '\x0': '\\\x0',
            '\\': '\\\\',
            '\n': '\\n' }
        return (''.join,)(lambda .0: for c in .0: d.get(c, c)(s))

    addslashes = classmethod(addslashes)
    
    def _printNewXCodeFormat(self, out, root, deep, enters = True):
        if isinstance(root, IterableUserDict):
            out.write('{')
            if enters:
                out.write('\n')
            
            isa = root.pop('isa', '')
            if isa != '':
                if enters:
                    out.write('\t' + deep)
                
                out.write('isa = ')
                self._printNewXCodeFormat(out, isa, '\t' + deep, enters = enters)
                out.write(';')
                if enters:
                    out.write('\n')
                else:
                    out.write(' ')
            
            for key in sorted(root.iterkeys()):
                if enters:
                    out.write('\t' + deep)
                
                if re.match(regex, key).group(0) == key:
                    out.write(key.encode('utf-8') + ' = ')
                else:
                    out.write('"' + key.encode('utf-8') + '" = ')
                if key == 'objects':
                    out.write('{')
                    if enters:
                        out.write('\n')
                    
                    sections = [
                        ('PBXBuildFile', False),
                        ('PBXCopyFilesBuildPhase', True),
                        ('PBXFileReference', False),
                        ('PBXFrameworksBuildPhase', True),
                        ('PBXGroup', True),
                        ('PBXAggregateTarget', True),
                        ('PBXNativeTarget', True),
                        ('PBXProject', True),
                        ('PBXResourcesBuildPhase', True),
                        ('PBXShellScriptBuildPhase', True),
                        ('PBXSourcesBuildPhase', True),
                        ('XCBuildConfiguration', True),
                        ('XCConfigurationList', True),
                        ('PBXTargetDependency', True),
                        ('PBXVariantGroup', True),
                        ('PBXReferenceProxy', True),
                        ('PBXContainerItemProxy', True)]
                    for section in sections:
                        if self.sections.get(section[0]) is None:
                            continue
                        
                        out.write('\n/* Begin %s section */' % section[0].encode('utf-8'))
                        self.sections.get(section[0]).sort(cmp = lambda x, y: cmp(x[0], y[0]))
                        for pair in self.sections.get(section[0]):
                            key = pair[0]
                            value = pair[1]
                            out.write('\n')
                            if enters:
                                out.write('\t\t' + deep)
                            
                            out.write(key.encode('utf-8'))
                            if key in self.uuids:
                                out.write(' /* ' + self.uuids[key].encode('utf-8') + ' */')
                            
                            out.write(' = ')
                            self._printNewXCodeFormat(out, value, '\t\t' + deep, enters = section[1])
                            out.write(';')
                        
                        out.write('\n/* End %s section */\n' % section[0].encode('utf-8'))
                    
                    out.write(deep + '\t}')
                else:
                    self._printNewXCodeFormat(out, root[key], '\t' + deep, enters = enters)
                out.write(';')
                if enters:
                    out.write('\n')
                    continue
                out.write(' ')
            
            root['isa'] = isa
            if enters:
                out.write(deep)
            
            out.write('}')
        elif isinstance(root, UserList):
            out.write('(')
            if enters:
                out.write('\n')
            
            for value in root:
                if enters:
                    out.write('\t' + deep)
                
                self._printNewXCodeFormat(out, value, '\t' + deep, enters = enters)
                out.write(',')
                if enters:
                    out.write('\n')
                    continue
            
            if enters:
                out.write(deep)
            
            out.write(')')
        elif len(root) > 0 and re.match(regex, root).group(0) == root:
            out.write(root.encode('utf-8'))
        else:
            out.write('"' + XcodeProject.addslashes(root.encode('utf-8')) + '"')
        if root in self.uuids:
            out.write(' /* ' + self.uuids[root].encode('utf-8') + ' */')
        

    
    def Load(cls, path):
        cls.plutil_path = os.path.join(os.path.split(__file__)[0], 'plutil')
        if not os.path.isfile(XcodeProject.plutil_path):
            cls.plutil_path = 'plutil'
        
        p = subprocess.Popen([
            XcodeProject.plutil_path,
            '-convert',
            'xml1',
            '-o',
            '-',
            path], stdout = subprocess.PIPE)
        (stdout, stderr) = p.communicate()
        if p.returncode != 0:
            print stdout
            return None
        tree = plistlib.readPlistFromString(stdout)
        return XcodeProject(tree, path)

    Load = classmethod(Load)
    
    def LoadFromXML(cls, path):
        tree = plistlib.readPlist(path)
        return XcodeProject(tree, path)

    LoadFromXML = classmethod(LoadFromXML)


class PBXWriter(plistlib.PlistWriter):
    
    def writeValue(self, value):
        if isinstance(value, (PBXList, PBXDict)):
            plistlib.PlistWriter.writeValue(self, value.data)
        else:
            plistlib.PlistWriter.writeValue(self, value)

    
    def simpleElement(self, element, value = None):
        if value is not None:
            value = _escapeAndEncode(value)
            self.writeln('<%s>%s</%s>' % (element, value, element))
        else:
            self.writeln('<%s/>' % element)



def _escapeAndEncode(text):
    m = re.compile('[\\x00\\x01\\x02\\x03\\x04\\x05\\x06\\x07\\x08\\x0b\\x0c\\x0e\\x0f\\x10\\x11\\x12\\x13\\x14\\x15\\x16\\x17\\x18\\x19\\x1a\\x1b\\x1c\\x1d\\x1e\\x1f]').search(text)
    if m is not None:
        raise ValueError("strings can't contains control characters; use plistlib.Data instead")
    m is not None
    text = text.replace('\r\n', '\n')
    text = text.replace('\r', '\n')
    text = text.replace('&', '&amp;')
    text = text.replace('<', '&lt;')
    text = text.replace('>', '&gt;')
    return text.encode('ascii', 'xmlcharrefreplace')


class Runner(object):
    
    def __init__(self, projectPath, unityProjectPath, pluginFolders, copyFilesIntoXcodeProject, disableDsymGeneration):
        projectFile = projectPath + '/Unity-iPhone.xcodeproj/project.pbxproj'
        project = XcodeProject.Load(projectFile)
        project.copyFilesIntoXcodeProject = copyFilesIntoXcodeProject
        project.log('----== USING BUILDER VERSION 3.0 ==----')
        self.projectPlistPath = projectPath + '/Info.plist'
        self.handlePlistAdditionsFile(project, self.projectPlistPath, unityProjectPath)
        self.weakFrameworks = []
        self.linkerFlags = []
        self.dynamicLibraries = []
        self.requiredFrameworks = []
        for pluginName in pluginFolders:
            syslog.syslog(syslog.LOG_ALERT, '--- About to handle ' + pluginName + ' ---')
            self.handlePlugin(project, unityProjectPath, pluginName, projectPath)
            print pluginName
            syslog.syslog(syslog.LOG_ALERT, '--- Finished handling ' + pluginName + ' ---')
        
        frameworksGroup = project.get_or_create_group('Frameworks')
        for f in self.requiredFrameworks:
            shouldWeakLink = f in self.weakFrameworks
            path = 'System/Library/Frameworks/' + f
            project.add_file_if_doesnt_exist(path, tree = 'SDKROOT', weak = shouldWeakLink, parent = frameworksGroup)
            project.log('adding framework: ' + f)
            if shouldWeakLink:
                project.log('weak linking framework: ' + f)
                continue
        
        dlibBaseDir = 'usr/lib/'
        for d in self.dynamicLibraries:
            project.add_file_if_doesnt_exist(dlibBaseDir + d, tree = 'SDKROOT', parent = frameworksGroup)
            project.log('adding dlib: ' + d)
        
        for flag in self.linkerFlags:
            project.add_other_ldflags(flag)
            project.log('adding other linker flag: ' + flag)
        
        if disableDsymGeneration:
            project.log('disabling dSYM generation (enjoy your super fast builds!)')
            project.modify_build_setting('DEBUG_INFORMATION_FORMAT', 'dwarf')
        
        syslog.syslog(syslog.LOG_ALERT, '--- saving Xcode project in its original format ---')
        project.save()

    
    def handlePlugin(self, p, unityProjectPath, pluginName, projectPath):
        p.pluginName = pluginName
        pluginPath = unityProjectPath + '/Assets/Editor/' + pluginName
        configPlistPath = pluginPath + '/config.plist'
        p.log('handling config.plist')
        info = plistlib.readPlist(configPlistPath)
        self.handleConfigPlistAdditionsKeys(p, info, self.projectPlistPath, unityProjectPath, pluginPath)
        (unusedPath, pluginRootFolder) = os.path.split(pluginPath)
        if p.has_group(pluginRootFolder):
            p.log('bailing out on processing plugin ' + pluginName + ' because we already processed it in a previous build')
            return None
        if info.has_key('weakLinkFrameworks'):
            pass
        1
        weakFrameworks = []
        continue
        weakFrameworks = [ f for f in weakFrameworks ]
        if info.has_key('linkerFlags'):
            pass
        1
        linkerFlags = []
        if info.has_key('dynamicLibraries'):
            pass
        1
        dynamicLibraries = []
        if info.has_key('requiredFrameworks'):
            pass
        1
        requiredFrameworks = []
        continue
        requiredFrameworks = [ f for f in requiredFrameworks ]
        (self.weakFrameworks.extend,)(lambda .0: for x in .0: if x not in self.weakFrameworks: xcontinue(weakFrameworks))
        (self.linkerFlags.extend,)(lambda .0: for x in .0: if x not in self.linkerFlags: xcontinue(linkerFlags))
        (self.dynamicLibraries.extend,)(lambda .0: for x in .0: if x not in self.dynamicLibraries: xcontinue(dynamicLibraries))
        (self.requiredFrameworks.extend,)(lambda .0: for x in .0: if x not in self.requiredFrameworks: xcontinue(requiredFrameworks))
        if info.has_key('enableExceptions'):
            pass
        1
        enableExceptions = False
        if enableExceptions:
            p.log('enabling Obj-C exceptions')
            p.modify_build_setting('GCC_ENABLE_OBJC_EXCEPTIONS', 'YES')
        
        sourceFileFolder = pluginPath
        if p.copyFilesIntoXcodeProject:
            destinationPath = os.path.join(projectPath, pluginRootFolder)
            sourceFileFolder = destinationPath
            if not os.path.isdir(destinationPath):
                shutil.copytree(pluginPath, destinationPath)
            
        
        p.log('adding files from folder: ' + sourceFileFolder)
        results = p.add_folder(sourceFileFolder, excludes = [
            '^.*\\.meta$',
            '^config\\.plist$'])
        for r in results:
            if r['isa'] == 'PBXBuildFile':
                continue
            
            if r['isa'] == 'PBXGroup':
                p.log('adding group ' + r['name'])
                continue
            
            if r['isa'] == 'PBXFileReference':
                p.log('adding file ' + r['name'])
                continue
                continue
            info['enableExceptions']
        

    
    def handlePlistAdditionsFile(self, p, projectPlistPath, unityProjectPath):
        
        try:
            infoPlist = plistlib.readPlist(projectPlistPath)
            additionsFilePath = unityProjectPath + '/Assets/Editor/Prime31/plistAdditions.plist'
            if os.path.isfile(additionsFilePath):
                p.log('merging in plistAdditions.plist data')
                additionsPlist = plistlib.readPlist(additionsFilePath)
                for k in additionsPlist:
                    if k != 'plistKeys':
                        infoPlist[k] = additionsPlist[k]
                        continue
                
                plistlib.writePlist(infoPlist, projectPlistPath)
        except Exception:
            e = None
            p.log('failed to merge infoplistAddtions.plist. exception: %s' % e)


    
    def handleConfigPlistAdditionsKeys(self, p, info, projectPlistPath, unityProjectPath, pluginPath):
        
        try:
            if info.has_key('pListAdditions'):
                pass
            1
            plistAdditions = []
            if len(plistAdditions) > 0:
                p.log('found plistAdditions key. Merging in plistAdditions key data now...')
                infoPlist = plistlib.readPlist(projectPlistPath)
                for pl in plistAdditions:
                    
                    try:
                        f = _[1]
                        data = f.read()
                    finally:
                        pass

                    hasData = len(data) != 0
                    if not hasData:
                        if pl['required']:
                            p.alert(pl['errorText'])
                            sys.exit()
                        
                    
                    if hasData:
                        key = pl['pListKey']
                        infoPlist[key] = data
                        continue
                
                plistlib.writePlist(infoPlist, projectPlistPath)
        except Exception:
            e = None
            p.log('failed to merge plistAdditions key data. exception: %s' % e)




class PluginHelper:
    
    def getAllPluginFoldersThatNeedProcessing(cls, sourceFolder):
        syslog.syslog(syslog.LOG_ALERT, '++++++ fetching all plugin folders that need to be processed')
        pluginFolders = PluginHelper.getAllPluginFolders(sourceFolder)
        syslog.syslog(syslog.LOG_ALERT, '++++++ total folders found: ' + str(len(pluginFolders)))
        syslog.syslog(syslog.LOG_ALERT, '++++++ preparing to filter plugins...')
        handledFolders = PluginHelper.getAllFoldersHandledByPostProcessScripts(sourceFolder)
        return (filter,)(lambda f: f not in handledFolders, pluginFolders)

    getAllPluginFoldersThatNeedProcessing = classmethod(getAllPluginFoldersThatNeedProcessing)
    
    def getAllPluginFolders(cls, sourceFolder):
        pluginFolders = []
        for folder in os.listdir(sourceFolder):
            fullPath = os.path.join(sourceFolder, folder)
            if str.startswith(folder, '.') and str.endswith(folder, '.meta') or not os.path.isdir(fullPath):
                continue
            
            if 'AdWhirl' in folder:
                continue
            
            if PluginHelper.doesFolderContainsConfig(fullPath):
                pluginFolders.append(folder)
                continue
        
        return pluginFolders

    getAllPluginFolders = classmethod(getAllPluginFolders)
    
    def getAllFoldersHandledByPostProcessScripts(cls, sourceFolder):
        pluginFolders = []
        for f in os.listdir(sourceFolder):
            fullPath = os.path.join(sourceFolder, f)
            if str.startswith(f, '.') and str.endswith(f, '.meta') or os.path.isdir(fullPath):
                continue
            
            if 'PostprocessBuildPlayer_' in f:
                temp = str.replace(f, 'PostprocessBuildPlayer_', '')
                temp = str.replace(temp, 'DISABLED', '')
                syslog.syslog(syslog.LOG_ALERT, 'folder has postprocess in it: %s' % temp)
                pluginFolders.append(temp)
                continue
        
        return pluginFolders

    getAllFoldersHandledByPostProcessScripts = classmethod(getAllFoldersHandledByPostProcessScripts)
    
    def doesFolderContainsConfig(cls, folder):
        if not os.path.exists(folder):
            return False
        for f in os.listdir(folder):
            if f == 'config.plist':
                return True
        
        return False

    doesFolderContainsConfig = classmethod(doesFolderContainsConfig)
    
    def processPlugins(cls, projectPath, unityProjectPath, pluginFolders, copyFilesIntoXcodeProject, disableDsymGeneration):
        
        try:
            run = Runner(projectPath, unityProjectPath, pluginFolders, copyFilesIntoXcodeProject, disableDsymGeneration)
        except Exception:
            e = None
            syslog.syslog(syslog.LOG_ALERT, 'runner failed with error: %s' % e)


    processPlugins = classmethod(processPlugins)

if __name__ == '__main__':
    syslog.openlog('Prime31')
    
    try:
        syslog.syslog(syslog.LOG_ALERT, 'Processing all folders')
        projectPath = sys.argv[1]   #第一个参数
        unityProjectPath = os.getcwd().replace('/Assets/Editor', '')    #unity工作路径
        if len(sys.argv) > 2:
            pass    
        copyFilesIntoXcodeProject = sys.argv[2] is '1'      #第二个参数，是否copy文件到xcode的目录
        if len(sys.argv) > 3:
            pass
        disableDsymGeneration = sys.argv[3] is '1'      
        syslog.syslog(syslog.LOG_ALERT, '++++++ using unityProjectPath: ' + projectPath)
        syslog.syslog(syslog.LOG_ALERT, '++++++ using Unity root path: ' + unityProjectPath)
        syslog.syslog(syslog.LOG_ALERT, '++++++ are we copying the files into the Xcode project: ' + str(copyFilesIntoXcodeProject))
        pluginFolders = PluginHelper.getAllPluginFoldersThatNeedProcessing(os.path.join(unityProjectPath, 'Assets/Editor'))
        #传入参数是当前工作路径，得到所有需要处理插件的个数//在Assets/Editor目录下
        syslog.syslog(syslog.LOG_ALERT, '++++++ total filtered plugins found: ' + str(len(pluginFolders)))
        PluginHelper.processPlugins(projectPath, unityProjectPath, pluginFolders, copyFilesIntoXcodeProject, disableDsymGeneration)
    except Exception:
        eee = None
        syslog.syslog(syslog.LOG_ALERT, '++++++ caught an exception in the post build: %s' % eee)


